package com.ly.oa.action.flow;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;

import org.apache.commons.lang.StringUtils;
import org.apache.velocity.app.VelocityEngine;
import org.apache.velocity.tools.generic.DateTool;
import org.jbpm.pvm.internal.model.Transition;
import org.springframework.ui.velocity.VelocityEngineUtils;

import com.google.gson.Gson;
import com.ly.core.jbpm.pv.ParamField;
import com.ly.core.util.ContextUtil;
import com.ly.core.util.JsonUtil;
import com.ly.core.web.action.BaseAction;
import com.ly.oa.model.flow.ProDefinition;
import com.ly.oa.model.flow.ProcessForm;
import com.ly.oa.model.flow.ProcessRun;
import com.ly.oa.model.flow.Transform;
import com.ly.oa.service.flow.FormDataService;
import com.ly.oa.service.flow.JbpmService;
import com.ly.oa.service.flow.ProDefinitionService;
import com.ly.oa.service.flow.ProcessFormService;
import com.ly.oa.service.flow.ProcessRunService;

import flexjson.JSONSerializer;

public class ProcessActivityAction extends BaseAction {
	@Resource
	private ProDefinitionService proDefinitionService;
	@Resource
	private ProcessRunService processRunService;

	@Resource
	private JbpmService jbpmService;
	@Resource
	VelocityEngine flowVelocityEngine;
	@Resource
	private FormDataService formDataService;
	@Resource
	private ProcessFormService processFormService;
	@Resource
	VelocityEngine velocityEngine;

	private String activityName;
	private Long runId;
	private Long taskId;
	/**
	 * 流程实例ID
	 */
	private String piId;

	public Long getTaskId() {
		return taskId;
	}

	public void setTaskId(Long taskId) {
		this.taskId = taskId;
	}

	public String getPiId() {
		return piId;
	}

	public void setPiId(String piId) {
		this.piId = piId;
	}

	public Long getRunId() {
		return runId;
	}

	public void setRunId(Long runId) {
		this.runId = runId;
	}

	public String getActivityName() {
		return activityName;
	}

	public void setActivityName(String activityName) {
		this.activityName = activityName;
	}

	/**
	 * 流程的定义ID
	 */
	private Long defId;

	public Long getDefId() {
		return defId;
	}

	public void setDefId(Long defId) {
		this.defId = defId;
	}

	/**
	 * 显示某个流程的任务表单信息
	 * 
	 * @return
	 * @throws Exception
	 */
	// public String get() throws Exception {
	// //流程名称
	// String processName=null;
	// if(defId!=null){
	// ProDefinition proDefinition=proDefinitionService.get(defId);
	// processName=proDefinition.getName();
	// }else if(piId!=null){
	// ProcessRun processRun=processRunService.getByPiId(piId);
	// processName=processRun.getProDefinition().getName();
	// runId=processRun.getRunId();
	// }
	//
	// String tempLocation="/form/"+ processName+"/" + activityName+ ".vm";
	//		
	// Map model=new HashMap();
	//		
	// if(runId!=null){
	// Map formDataMap=formDataService.getFromDataMap(runId, activityName);
	// model.putAll(formDataMap);
	// }
	// model.put("curUser", ContextUtil.getCurrentUser());
	// String
	// formUiJs=VelocityEngineUtils.mergeTemplateIntoString(velocityEngine,tempLocation
	// , "UTF-8", model);
	//		
	// logger.info("formUIJs:" + formUiJs);
	//		
	// setJsonString("{success:true,data:"+formUiJs+"}");
	//		
	// return SUCCESS;
	// }
	public String get() throws Exception {
		ProDefinition proDefinition = getProDefinition();
		String processName = proDefinition.getName();
		if (StringUtils.isEmpty(this.activityName)) {
			this.activityName = this.jbpmService.getStartNodeName(proDefinition);
		}
		String tempLocation = ProcessActivityAssistant.getFormPath(processName,this.activityName);
		Map model = new HashMap();
		Map formDataMap = null;
		if (this.runId != null) {
			formDataMap = this.formDataService.getFromDataMap(this.runId,this.activityName);
		}
		Map fieldsMap = ProcessActivityAssistant.constructFieldMap(processName,
				this.activityName);
		Iterator fieldNames = fieldsMap.keySet().iterator();
		while (fieldNames.hasNext()) {
			String fieldName = (String) fieldNames.next();
			if (formDataMap != null) {
				Object fieldVal = formDataMap.get(fieldName);
				model.put(fieldName, fieldVal);
			}
			
			if (!model.containsKey(fieldName)) {
				model.put(fieldName, "");
			}
		}
		if (this.taskId != null) {
			ProcessRun processRun = this.processRunService.getByTaskId(this.taskId.toString());
			Map processRunVars = this.processFormService.getVariables(processRun.getRunId());
			List<Transition> trans = this.jbpmService.getTransitionsByTaskId(this.taskId.toString());
			List allTrans = new ArrayList();
			for (Transition tran : trans) {
				allTrans.add(new Transform(tran));
			}
			model.putAll(processRunVars);
			model.put("nextTrans", allTrans);
		}
		model.put("currentUser", ContextUtil.getCurrentUser());
		model.put("dateTool", new DateTool());
		String formUiJs = "";
		try {
			formUiJs = VelocityEngineUtils.mergeTemplateIntoString(flowVelocityEngine, tempLocation, "UTF-8", model);
		} catch (Exception ex) {
			formUiJs = VelocityEngineUtils.mergeTemplateIntoString(
					flowVelocityEngine, ProcessActivityAssistant.getCommonFormPath(this.activityName), "UTF-8",	model);
			ex.printStackTrace();
		}
		if (StringUtils.isEmpty(formUiJs)) {
			formUiJs = "[]";
		}
		System.out.println(formUiJs);
		setJsonString(formUiJs);
		return SUCCESS;
	}

	/**
	 * 保存申请
	 */
	public String save() {
		logger.info("save the Process Run Information");
		//
		// Map fieldMap = constructFieldMap();
		//
		// if (defId != null) {// 添加流程申请
		// ProDefinition proDefinition = proDefinitionService.get(defId);
		// processRunService.saveProcessRun(proDefinition,
		// fieldMap,activityName, false);
		// } else {// 更新流程申请
		// // TODO
		// // ProcessRun processRun=processRunService.get(runId);
		//
		// }
		FlowRunInfo flowRunInfo = getFlowRunInfo();
		if (this.runId != null) {
			ProcessRun processRun = (ProcessRun) this.processRunService.get(this.runId);
			processRun.setCreatetime(new Date());
			ProcessForm processForm = this.processFormService.getByRunIdActivityName(this.runId, this.activityName);
			processForm.setCreatetime(new Date());
			if (processForm != null) {
				this.processRunService.saveProcessRun(processRun, processForm,flowRunInfo);
			}
		} else if (this.defId != null) {
			ProcessRun processRun = initNewProcessRun();
			processRun.setCreatetime(new Date());
			ProcessForm processForm = initNewProcessForm(processRun);
			processForm.setCreatetime(new Date());
			this.processRunService.saveProcessRun(processRun, processForm,flowRunInfo);
		}
		setJsonString("{success:true}");
		return SUCCESS;
	}

	protected ProcessRun initNewProcessRun() {
		ProDefinition proDefinition = (ProDefinition) this.proDefinitionService.get(this.defId);
		return this.processRunService.initNewProcessRun(proDefinition);
	}

	protected ProcessForm initNewProcessForm(ProcessRun processRun) {
		ProcessForm processForm = new ProcessForm();
		processForm.setActivityName(this.activityName);
		processForm.setProcessRun(processRun);
		return processForm;
	}

	/**
	 * 保存申请并启动流程
	 * 
	 * @return
	 */
	// public String start() {
	// logger.info("start the Process Run Information");
	// ProDefinition proDefinition = proDefinitionService.get(defId);
	// Map fieldMap = constructFieldMap();
	// processRunService.saveProcessRun(proDefinition, fieldMap,
	// activityName,true);
	// setJsonString("{success:true}");
	// return SUCCESS;
	// }

	/**
	 * 下一步
	 * 
	 * @return
	 */
	public String next() {
//		String signalName = getRequest().getParameter("signalName");
//		String xml = jbpmService.getProcessDefintionXMLByPiId(piId);
//		String nodeType = jbpmService.getNodeType(xml, activityName);
//		// 完成当前任务
//		Map<String, ParamField> fieldMap = constructFieldMap();
//		processRunService.saveAndNextstep(piId, activityName, signalName,fieldMap);
//		setJsonString("{success:true}");
////		
		FlowRunInfo flowRunInfo = getFlowRunInfo();
		this.processRunService.saveAndNextStep(flowRunInfo);
		setJsonString("{success:true}");
		return SUCCESS;
	}

	public String freeTrans() {
		Gson gson = new Gson();
		StringBuffer sb = new StringBuffer();

		sb.append("[");

		List<Transition> trans = this.jbpmService
				.getFreeTransitionsByTaskId(this.taskId.toString());

		for (Transition tran : trans) {
			sb.append("[").append(gson.toJson(tran.getName())).append(",")
					.append(gson.toJson(tran.getDestination().getName()))
					.append("],");
		}

		if (trans.size() > 0) {
			sb.deleteCharAt(sb.length() - 1);
		}

		sb.append("]");

		setJsonString(sb.toString());

		return "success";
	}

	/**
	 * 取得当前任务所有出口
	 * 
	 * @return
	 */
	public String trans() {
		List<Transition> trans = jbpmService
				.getTransitionsForSignalProcess(piId);
		List<Transform> allTrans = new ArrayList<Transform>();

		for (Transition tran : trans) {
			allTrans.add(new Transform(tran));
		}

		JSONSerializer serializer = JsonUtil.getJSONSerializer();
		String result = serializer.serialize(allTrans);
		logger.info("result:" + result);
		setJsonString("{success:true,data:" + result + "}");
		return SUCCESS;
	}

	/**
	 * 构建提交的流程或任务对应的表单信息字段
	 * 
	 * @return
	 */
	// protected Map<String, ParamField> constructFieldMap() {
	// HttpServletRequest request = getRequest();
	//
	// String processName = null;
	// if (defId != null) {
	// ProDefinition proDefinition = proDefinitionService.get(defId);
	// processName = proDefinition.getName();
	// } else if (piId != null) {
	// ProcessRun processRun = processRunService.getByPiId(piId);
	// processName = processRun.getProDefinition().getName();
	// }
	//
	// String fieldsXmlLoaction = "velocity/form/" + processName + "/"
	// + activityName + "-fields.xml";
	// Map<String, ParamField> map = new HashMap<String, ParamField>();
	// try {
	// InputStream is = Thread.currentThread().getContextClassLoader()
	// .getResourceAsStream(fieldsXmlLoaction);
	// Document doc = XmlUtil.load(is);
	// Element fields = doc.getRootElement();
	// List<Element> els = fields.elements();
	// for (Element el : els) {
	// String name = el.attribute("name").getValue();
	// String isShow = el.attribute("isShowed").getValue();
	// Attribute attLabel = el.attribute("label");
	// Attribute attType = el.attribute("type");
	// Attribute attLength = el.attribute("length");
	// String label = attLabel == null ? name : attLabel.getValue();
	// String type = attType == null ? ParamField.FIELD_TYPE_VARCHAR:
	// attType.getValue();
	// Integer length = attLength == null ? 0 : new
	// Integer(attLength.getValue());
	// ParamField pf = new ParamField(name, type, label, length,new
	// Short(isShow));
	// String value = request.getParameter(name);
	// pf.setValue(value);
	// map.put(name, pf);
	// }
	// } catch (Exception ex) {
	// logger.error("error when read the file from " + activityName+
	// "-fields.xml: " + ex.getMessage());
	// }
	//
	// return map;
	// }
	/** 获得自定义表单的字段 **/
	protected Map<String, ParamField> constructFieldMap() {
		HttpServletRequest request = getRequest();
		ProDefinition proDefinition = getProDefinition();
		if (StringUtils.isEmpty(this.activityName)) {
			this.activityName = this.jbpmService
					.getStartNodeName(proDefinition);
		}
		Map map = ProcessActivityAssistant.constructFieldMap(proDefinition
				.getName(), this.activityName);
		Iterator fieldNames = map.keySet().iterator();
		while (fieldNames.hasNext()) {
			String name = (String) fieldNames.next();
			ParamField pf = (ParamField) map.get(name);
			pf.setName(pf.getName().replace(".", "_"));
			pf.setValue(request.getParameter(name));
		}
		return map;
	}

	protected ProDefinition getProDefinition() {
		ProDefinition proDefinition = null;
		if (this.runId != null) {
			ProcessRun processRun = (ProcessRun) this.processRunService.get(this.runId);
			proDefinition = processRun.getProDefinition();
		} else if (this.defId != null) {
			proDefinition = (ProDefinition) this.proDefinitionService.get(this.defId);
		} else {
			ProcessRun processRun = this.processRunService.getByTaskId(taskId.toString());
			proDefinition = processRun.getProDefinition();
		}
		return proDefinition;
	}

	protected FlowRunInfo getFlowRunInfo() {
		FlowRunInfo info = new FlowRunInfo(getRequest());
		Map fieldMap = constructFieldMap();
		info.setParamFields(fieldMap);
		return info;
	}
	
}
